import frappe
from frappe import _
import requests
import json
from datetime import datetime, timedelta
import hashlib
from frappe_wxwork.oauth2_logins import get_wx_corpid_secret

class WXWorkContactSync:
    def __init__(self, corpid=None, corpsecret=None):
        if not corpid:
            corpid, corpsecret = get_wx_corpid_secret()
        self.corpid = corpid
        self.secret = corpsecret
        self.access_token = None
        self.token_expire_time = None

    def get_access_token(self, force_refresh=False):
        """获取或刷新Access Token"""
        current_time = datetime.now()
        
        if (self.access_token and not force_refresh and self.token_expire_time):
            if isinstance(self.token_expire_time, (int, float)):
                expire_time = datetime.fromtimestamp(self.token_expire_time)
            else:
                expire_time = self.token_expire_time
            
            if current_time < expire_time:
                return self.access_token

        url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken"
        params = {
            "corpid": self.corpid,
            "corpsecret": self.secret
        }

        try:
            response = requests.get(url, params=params, timeout=30)
            result = response.json()

            if result.get("errcode") == 0:
                self.access_token = result.get("access_token")
                expire_in = result.get("expires_in", 7200) - 300
                self.token_expire_time = datetime.now().timestamp() + expire_in
                frappe.logger().info("成功获取企业微信Access Token")
                return self.access_token
            else:
                error_msg = f"获取Access Token失败: {result.get('errmsg')} (错误码: {result.get('errcode')})"
                frappe.log_error(error_msg, "企业微信通讯录同步")
                frappe.throw(_(error_msg))

        except requests.exceptions.RequestException as e:
            error_msg = f"网络请求失败: {str(e)}"
            frappe.log_error(error_msg, "企业微信通讯录同步")
            frappe.throw(_(error_msg))

    def get_department_list(self, department_id=None):
        """获取部门列表"""
        access_token = self.get_access_token()
        url = "https://qyapi.weixin.qq.com/cgi-bin/department/list"
        params = {
            "access_token": access_token
        }
        if department_id:
            params["id"] = department_id

        try:
            response = requests.get(url, params=params, timeout=30)
            result = response.json()

            if result.get("errcode") == 0:
                departments = result.get("department", [])
                frappe.logger().info(f"成功获取 {len(departments)} 个部门")
                return departments
            else:
                error_msg = f"获取部门列表失败: {result.get('errmsg')}"
                frappe.log_error(error_msg, "企业微信通讯录同步")
                return []

        except Exception as e:
            error_msg = f"获取部门列表异常: {str(e)}"
            frappe.log_error(error_msg, "企业微信通讯录同步")
            return []

    def get_simple_user_list(self, department_id=1, fetch_child=1):
        """使用 simplelist 接口获取部门成员"""
        access_token = self.get_access_token()
        url = "https://qyapi.weixin.qq.com/cgi-bin/user/simplelist"
        params = {
            "access_token": access_token,
            "department_id": department_id,
            "fetch_child": fetch_child
        }

        try:
            response = requests.get(url, params=params, timeout=30)
            result = response.json()

            if result.get("errcode") == 0:
                users = result.get("userlist", [])
                frappe.logger().info(f"成功获取 {len(users)} 个简单用户信息")
                return users
            else:
                error_msg = f"获取用户简单列表失败: {result.get('errmsg')} (部门ID: {department_id})"
                frappe.log_error(error_msg, "企业微信通讯录同步")
                return []

        except Exception as e:
            error_msg = f"获取用户简单列表异常: {str(e)}"
            frappe.log_error(error_msg, "企业微信通讯录同步")
            return []

    def get_user_detail(self, userid):
        """获取成员详细信息"""
        access_token = self.get_access_token()
        url = "https://qyapi.weixin.qq.com/cgi-bin/user/get"
        params = {
            "access_token": access_token,
            "userid": userid
        }

        try:
            response = requests.get(url, params=params, timeout=30)
            result = response.json()

            if result.get("errcode") == 0:
                return result
            else:
                error_msg = f"获取用户详情失败: {result.get('errmsg')} (用户: {userid})"
                frappe.log_error(error_msg, "企业微信通讯录同步")
                return None

        except Exception as e:
            error_msg = f"获取用户详情异常: {str(e)}"
            frappe.log_error(error_msg, "企业微信通讯录同步")
            return None

    def sync_all_contacts(self):
        """同步所有通讯录数据"""
        try:
            
            # 1. 同步部门
            departments = self.get_department_list()
            dept_count = self.sync_departments(departments)

            # 2. 同步用户（从根部门开始，获取所有子部门用户）
            user_count = self.sync_users_from_departments(departments)

            frappe.db.commit()

            return {
                "success": True,
                "department_count": dept_count,
                "user_count": user_count,
                "message": f"同步完成！部门: {dept_count} 个, 用户: {user_count} 个"
            }

        except Exception as e:
            frappe.db.rollback()
            error_msg = f"同步通讯录失败: {str(e)}"
            frappe.log_error(error_msg, frappe.get_traceback(with_context=True))
            return {
                "success": False,
                "error": error_msg
            }

    def sync_departments(self, departments):
        """同步部门数据到ERPNext"""
        count = 0
        for dept in departments:
            try:
                #self.create_or_update_department(dept)
                count += 1
            except Exception as e:
                frappe.log_error(f"同步部门失败 {dept.get('name')}: {str(e)}", frappe.get_traceback(with_context=True))

        return count

    def sync_users_from_departments(self, departments):
        """从所有部门同步用户"""
        all_users = []
        userid_set = set()

        # 获取每个部门的用户
        for dept in departments:
            dept_id = dept.get("id")
            users = self.get_simple_user_list(dept_id, fetch_child=0)  # 不获取子部门，避免重复
            
            for user in users:
                userid = user.get("userid")
                if userid and userid not in userid_set:
                    userid_set.add(userid)
                    all_users.append(user)

        # 同步用户数据
        count = 0
        for user in all_users:
            try:
                if self.create_or_update_user(user):
                    count += 1
            except Exception as e:
                frappe.log_error(f"同步用户失败 {user.get('userid')}: {str(e)}", frappe.get_traceback(with_context=True))

        return count

    def create_or_update_user(self, user_data):
        """创建或更新用户"""
        userid = user_data.get("userid")
        if not userid:
            return False

        # 获取用户详细信息
        detail_info = self.get_user_detail(userid)
        if not detail_info:
            return False

        # 准备用户数据
        user_info = {
            "corpid": self.corpid,
            "wechat_nickname": detail_info.get("name", "").strip(),
            "last_sync": frappe.utils.now()
        }

        # 查找是否已存在
        existing = frappe.get_value("WXWork User", {"userid": userid})

        if existing:
            # 更新现有用户
            doc = frappe.get_doc("WXWork User", existing)
            doc.update(user_info)
            doc.save(ignore_permissions=True)
            frappe.logger().info(f"更新用户: {user_info['wechat_nickname']} ")
        else:
            # 创建新用户
            user_info.update({
                "doctype": "WXWork User",
                "userid": userid
            })
            doc = frappe.get_doc(user_info)
            doc.insert(ignore_permissions=True)
            frappe.logger().info(f"创建用户: {user_info['wechat_nickname']}")

        return True

    def test_connection(self):
        """测试连接"""
        try:
            token = self.get_access_token()
            if token:
                return {"success": True, "message": "连接测试成功"}
            else:
                return {"success": False, "message": "获取Token失败"}
        except Exception as e:
            return {"success": False, "message": str(e)}